home *** CD-ROM | disk | FTP | other *** search
- /*
- BiT '98
- completely rewritten for obvious reasons...
- first of all, it didnt work (sigsegv and shit)
- second.. my house got raided and everything was taken
- third.. i have nothing to do waiting for my phone line to return.......
- */
-
- /*
- Killing processes with (e)uid==0 if they aint owned by root or anyone
- in /etc/rootusers, except if the process name is in /etc/suids
-
- bugfix: forgot a signal() in the SIGHUP handler, im to lazy to use
- sigaction()
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <netdb.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <signal.h>
- #include <pwd.h>
- #include <time.h>
-
- #define VERSION "0.6"
- #define ROOTUSERS "/etc/rootusers"
- #define SUIDS "/etc/suids"
- #define PIDFILE "/var/run/rootcheck.pid"
- #define EMAIL "bit@localhost" /* you might want to change this */
- #define NETSTAT "/bin/netstat"
- #define W "/usr/bin/w"
- #define LAST "/usr/bin/last"
-
- struct rootcheck {
- char name[256];
- pid_t pid, ppid;
- uid_t uid, euid;
- };
-
- uid_t rootusers[16]; /* more then 16 roots?! */
- char suids[64][256]; /* what about removing some root suids? */
- int nrootusers, nsuids;
-
- void sighup(int s);
- void rehash(int status);
- int okuid(uid_t uid);
- void foreverloop(void);
- struct rootcheck *getinfo(char *d_name);
- struct rootcheck *trace_to_init(struct rootcheck par);
- void checkup(char *d_name);
- void mail_n_kill(struct rootcheck cur, struct rootcheck par);
-
- void main(int argc, char **argv)
- {
- int i;
- char buf[512];
-
- printf("rootcheck %s - BiT '98\n\n", VERSION);
-
- if (geteuid())
- printf("I prefer euid 0\n"), exit(-1);
-
- if ((i = open(PIDFILE, O_RDONLY)) != -1) {
- read(i, buf, sizeof(buf));
- if (kill(atoi(buf), SIGCHLD) != -1)
- printf("Allready running.\n"), exit(-1);
- close(i);
- }
- printf("Loading init files...");
- rehash(0);
- printf("done\nSetting up HUP handler and detaching...");
- fflush(stdout);
-
- signal(SIGHUP, (void *) &sighup);
- if ((i = fork()) == -1)
- printf("can't fork()?!\n"), exit(-1);
- if (i)
- putchar('\n'), close(0), close(1), close(2), exit(-1);
-
- if ((i = open(PIDFILE, O_WRONLY | O_CREAT)) != -1) {
- sprintf(buf, "%d", getpid());
- write(i, buf, strlen(buf));
- close(i);
- }
- foreverloop();
- }
-
- void foreverloop(void)
- {
- DIR *procdir;
- struct dirent *pproc;
- struct stat sbuf;
- chdir("/proc");
- procdir = opendir("."); /* if this doesnt work............ */
-
- while (1) {
- if ((pproc = readdir(procdir)) != NULL) {
- if (stat(pproc->d_name, &sbuf) == -1)
- continue;
- if (S_ISDIR(sbuf.st_mode))
- checkup(pproc->d_name);
- } else
- rewinddir(procdir);
- usleep(10); /* yaya lemme eat yer cpu */
- }
- }
-
- void checkup(char *d_name)
- {
- struct rootcheck *p, cur, par;
- char buf[512];
-
- if (!strcmp(d_name, "scsi") || !strcmp(d_name, "net") || !strcmp(d_name, "sys")
- || !strcmp(d_name, "self") || !strcmp(d_name, ".")
- || !strcmp(d_name, "..") || !strcmp(d_name, "1"))
- return;
-
-
- if ((p = getinfo(d_name)) == NULL)
- return;
- memcpy(&cur, p, sizeof(struct rootcheck));
-
- if (cur.ppid == 1)
- return;
-
- if (cur.uid && cur.euid)
- return;
-
- if (oksuid(cur.name))
- return;
-
- if ((p = trace_to_init(cur)) == NULL)
- return;
- memcpy(&par, p, sizeof(struct rootcheck));
-
- if (okuid(par.uid))
- return;
-
- mail_n_kill(cur, par);
- }
-
- void mail_n_kill(struct rootcheck cur, struct rootcheck par)
- {
- FILE *fd;
- char buf[256], fn[256];
- struct passwd *pwd;
-
- unsetenv("IFS");
- srand(time(NULL));
- pwd = getpwuid(par.uid);
- sprintf(fn, "/tmp/rc%d", rand());
-
- fd = fopen(fn, "w");
- sprintf(buf, "User %s got euid 0 from %s\n\nSystem data follows:\n\n",
- pwd->pw_name, cur.name);
- fputs(buf, fd);
- fclose(fd);
-
- sprintf(buf, "%s -a -n >> %s", NETSTAT, fn);
- system(buf);
-
- sprintf(buf, "%s >> %s", W, fn);
- system(buf);
-
- sprintf(buf, "%s -20 >> %s", LAST, fn);
- system(buf);
-
- sprintf(buf, "cat %s | mail %s", fn, EMAIL);
- system(buf);
-
- unlink(fn);
- kill(par.pid, 9); /* SPLAM! */
- }
-
- /* not really correct name, traces until parents uid is 0 */
-
- struct rootcheck *trace_to_init(struct rootcheck par)
- {
- static struct rootcheck *p, cur, old;
- char buf[512];
-
- sprintf(buf, "%d", par.ppid);
- if ((p = getinfo(buf)) == NULL)
- return NULL;
- memcpy(&old, &par, sizeof(struct rootcheck));
- memcpy(&cur, p, sizeof(struct rootcheck));
-
- while (1) {
- if (cur.uid == 0 && cur.euid == 0)
- return &old;
- sprintf(buf, "%d", cur.ppid);
- if ((p = getinfo(buf)) == NULL)
- return NULL;
- memcpy(&old, &cur, sizeof(struct rootcheck));
- memcpy(&cur, p, sizeof(struct rootcheck));
- }
- }
-
- int oksuid(char *owner)
- {
- int i;
-
- for (i = 0; i < nsuids; i++)
- if (strcasecmp(suids[i], owner) == 0)
- return 1;
- return 0;
- }
-
- int okuid(uid_t uid)
- {
- int i;
-
- if (!uid)
- return 1;
-
- for (i = 0; i < nrootusers; i++) {
- if (rootusers[i] == uid)
- return 1;
- }
- return 0;
- }
-
- struct rootcheck *getinfo(char *d_name)
- {
- static struct rootcheck rc;
- char buf[512], fn[512], *p, i;
- FILE *fd;
-
- sprintf(fn, "%s/status", d_name);
-
- if ((fd = fopen(fn, "r")) == NULL)
- return NULL;
-
- if (fgets(buf, sizeof(buf), fd) == NULL)
- return NULL;
- buf[strlen(buf) - 1] = 0;
- strncpy(rc.name, (buf + 6), sizeof(rc.name));
-
- if (fgets(buf, sizeof(buf), fd) == NULL)
- return NULL;
-
- if (fgets(buf, sizeof(buf), fd) == NULL)
- return NULL;
- rc.pid = atoi((buf + 5));
-
- if (fgets(buf, sizeof(buf), fd) == NULL)
- return NULL;
- rc.ppid = atoi((buf + 6));
-
- if (fgets(buf, sizeof(buf), fd) == NULL)
- return NULL;
-
- p = buf + 5;
- for (i = 0; *(p + i) != '\t'; i++);
- *(p + i) = 0;
- rc.uid = atoi(p);
-
- p += i;
- p++;
- for (i = 0; *(p + i) != '\t'; i++);
- *(p + i) = 0;
- rc.euid = atoi(p);
- fclose(fd);
-
- return &rc;
- }
-
- void sighup(int s)
- {
- signal(SIGHUP, (void *) &sighup);
- rehash(1);
- }
-
- void rehash(int status)
- {
- FILE *fd;
- char buf[256];
- struct passwd *pwd;
-
- nsuids = nrootusers = 0;
-
- fd = fopen(ROOTUSERS, "r");
- if (fd == NULL && !status)
- printf("can't open %s..", ROOTUSERS);
-
- if (fd) {
- while (fgets(buf, sizeof(buf), fd) != NULL) {
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = 0;
- if ((pwd = getpwnam(buf)) == NULL)
- break;
- rootusers[nrootusers++] = pwd->pw_uid;
- }
- fclose(fd);
- }
- fd = fopen(SUIDS, "r");
- if (fd == NULL && !status)
- printf("can't open %s..", SUIDS);
-
- if (fd) {
- while (fgets(buf, sizeof(buf), fd) != NULL) {
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = 0;
- buf[255] = 0;
- strcpy(suids[nsuids++], buf);
- }
- fclose(fd);
- }
- }
-